package cn.edu.nju.software.greencreditsystem.DAOImpl;

import cn.edu.nju.software.greencreditsystem.DAO.RepaymentRecordDAO;
import cn.edu.nju.software.greencreditsystem.domain.Enterprise;
import cn.edu.nju.software.greencreditsystem.domain.RepaymentRecord;
import cn.edu.nju.software.greencreditsystem.factory.SessionPool;
import java.awt.Color;
import java.awt.Font;
import java.awt.image.BufferedImage;
import java.sql.Date;
import java.text.SimpleDateFormat;
import java.util.List;
import org.hibernate.Query;
import org.hibernate.Session;
import org.jfree.chart.ChartFactory;
import org.jfree.chart.JFreeChart;
import org.jfree.chart.plot.CategoryPlot;
import org.jfree.chart.plot.PlotOrientation;
import org.jfree.chart.renderer.category.BarRenderer;
import org.jfree.data.category.DefaultCategoryDataset;

/**
 * 作者：何启睿
 * 创建时间：2011-8-7
 * 类描述：Repayment类DAO实现
 */
public class RepaymentRecordDAOImpl implements RepaymentRecordDAO
{

    @Override
    public boolean save(RepaymentRecord rr)
    {
        boolean result = false;
        
        Session s = SessionPool.getSession();
        s.beginTransaction();
        try
        {
            s.save(rr);
            s.getTransaction().commit();
            result = true;
        }catch(Exception ex)
        {
            ex.printStackTrace();
            s.getTransaction().rollback();
        }finally
        {
            s.close();
        }
        
        return result;
    }

    @Override
    public boolean delete(RepaymentRecord rr)
    {
        boolean result = false;
        
        Session s = SessionPool.getSession();
        s.beginTransaction();
        try
        {
            s.delete(rr);
            s.getTransaction().commit();
            result = true;
        }catch(Exception ex)
        {
            ex.printStackTrace();
            s.getTransaction().rollback();
        }finally
        {
            s.close();
        }
        
        return result;
    }

    @Override
    public RepaymentRecord getById(int id)
    {
        RepaymentRecord result = null;
        
        Session s = SessionPool.getSession();
        s.beginTransaction();
        try
        {
            result = (RepaymentRecord) s.get(RepaymentRecord.class, id);
            s.getTransaction().commit();
        }catch(Exception ex)
        {
            ex.printStackTrace();
            s.getTransaction().rollback();
        }finally
        {
            s.close();
        }
        
        return result;
    }

    @Override
    public boolean update(RepaymentRecord rr)
    {
        boolean result = false;
        
        Session s = SessionPool.getSession();
        s.beginTransaction();
        try
        {
            s.update(rr);
            s.getTransaction().commit();
            result = true;
        }catch(Exception ex)
        {
            ex.printStackTrace();
            s.getTransaction().rollback();
        }finally
        {
            s.close();
        }
        
        return result;
    }

    @Override
    public List<RepaymentRecord> getByEnterprise(int enterpriseID)
    {
        List<RepaymentRecord> result = null;
        
        Session s = SessionPool.getSession();
        s.beginTransaction();
        try
        {
            Query q = s.createQuery("from RepaymentRecord rr where rr.enterprise.id=" + enterpriseID
                                     + " order by rr.planDate asc");
            result = q.list();
            s.getTransaction().commit();
        }catch(Exception ex)
        {
            ex.printStackTrace();
            s.getTransaction().rollback();
        }finally
        {
            s.close();
        }
        
        return result;
    }

    @Override
    public boolean repay(int enterpriseID, Date planDate, Date realDate)
    {
        boolean result = false;
        
        Session s = SessionPool.getSession();
        s.beginTransaction();
        try
        {
            Query q = s.createQuery("from RepaymentRecord where enterprise.id = " + enterpriseID + ":en and planDate = :pd");
            q.setDate("pd", planDate);
            List<RepaymentRecord> temp = q.list();
            
            for(int i = 0; i < temp.size(); i++)
                temp.get(i).setHasPaid(true);
            
            s.getTransaction().commit();
            result = true;
        }catch(Exception ex)
        {
            ex.printStackTrace();
            s.getTransaction().rollback();
        }finally
        {
            s.close();
        }
        
        return result;
    }

    @Override
    public double getTotal(int enterpriseID, Date date)
    {
        Double result = null;
        
        Session s = SessionPool.getSession();
        s.beginTransaction();
        try
        {
            Query q = null;
            if(date == null)
            {
                q = s.createQuery("select sum(rr.amount) from RepaymentRecord rr"
                                        + " where rr.enterprise.id=" + enterpriseID);
            }else
            {
                q = s.createQuery("select sum(rr.amount) from RepaymentRecord rr"
                                        + " where rr.enterprise.id=" + enterpriseID
                                        + " and rr.planDate <= :date");
                q.setDate("date", date);
            }
            
            result = (Double) q.uniqueResult();
            s.getTransaction().commit();
        }catch(Exception ex)
        {
            ex.printStackTrace();
            s.getTransaction().rollback();
        }finally
        {
            s.close();
        }
        
        return result;
    }

    @Override
    public double getPaid(int enterpriseID, Date date)
    {
        double result = 0;
        
        Session s = SessionPool.getSession();
        s.beginTransaction();
        try
        {
            Query q = null;
            if(date == null)
            {
                q = s.createQuery("from RepaymentRecord"
                                        + " where enterprise.id=" + enterpriseID
                                        + " and hasPaid=true");
            }else
            {
                q = s.createQuery("from RepaymentRecord"
                                        + " where enterprise.id=" + enterpriseID
                                        + " and realDate <= :date"
                                        + " and hasPaid=true");
                q.setDate("date", date);
            }
            
            List<RepaymentRecord> temp = q.list();
            for(int i = 0; i < temp.size(); i++)
                result += temp.get(i).getAmount();
            
            s.getTransaction().commit();
        }catch(Exception ex)
        {
            ex.printStackTrace();
            s.getTransaction().rollback();
        }finally
        {
            s.close();
        }
        
        return result;
    }

    @Override
    public RepaymentRecord getNextUnpaid(int enterpriseID)
    {
        RepaymentRecord result = null;
        
        Session s = SessionPool.getSession();
        s.beginTransaction();
        try
        {
            Date today = new Date(System.currentTimeMillis());
            Query q = s.createQuery("from RepaymentRecord where planDate >= :today"
                                    + " and hasPaid=false order by planDate asc");
            q.setDate("today", today);
            
            List<RepaymentRecord> temp = q.list();
            if(temp.size() > 0)
                result = (RepaymentRecord) temp.get(0);
            
            s.getTransaction().commit();
        }catch(Exception ex)
        {
            ex.printStackTrace();
            s.getTransaction().rollback();
        }finally
        {
            s.close();
        }
        
        return result;
    }

    @Override
    public boolean deleteAllById(int enterpriseID)
    {
        boolean result = false;
        
        Session s = SessionPool.getSession();
        s.beginTransaction();
        try
        {
            s.createQuery("delete from RepaymentRecord "
                        + "where enterprise.id = " + enterpriseID)
                        .executeUpdate();
            s.getTransaction().commit();
            result = true;
        }catch(Exception ex)
        {
            ex.printStackTrace();
            s.getTransaction().rollback();
        }finally
        {
            s.close();
        }
        
        return result;
    }

    @Override
    public BufferedImage drawImage(int enterpriseID, int width, int height)
    {        
        Enterprise en = null;
        Session s = SessionPool.getSession();
        s.beginTransaction();
        try
        {
            en = (Enterprise) s.get(Enterprise.class, enterpriseID);
            s.getTransaction().commit();
        }catch(Exception ex)
        {
            ex.printStackTrace();
            s.getTransaction().rollback();
        }finally
        {
            s.close();
        }
        
        DefaultCategoryDataset dataset = new DefaultCategoryDataset();
        SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM");
        List<RepaymentRecord> records = getByEnterprise(enterpriseID);
        for(int i = 0; i < records.size(); i++)
        {
            RepaymentRecord record = records.get(i);
            dataset.addValue(record.getAmount(), "计划", dateFormat.format(record.getPlanDate()));
            if(record.getHasPaid())
                dataset.addValue(record.getAmount(), "实际", dateFormat.format(record.getPlanDate()));
        }
        
        JFreeChart chart = ChartFactory.createBarChart3D(en.getName() + "还贷记录", "日期", "金额", dataset, PlotOrientation.VERTICAL, true, true, false);
        chart.setBackgroundPaint(Color.WHITE);
        chart.getTitle().setFont(new Font("Helvetica",Font.PLAIN,13));
        chart.getLegend().setItemFont(new Font("Helvetica",Font.PLAIN,13));
        CategoryPlot plot = chart.getCategoryPlot();
        plot.getDomainAxis().setLabelFont(new Font("Helvetica",Font.PLAIN,13));
        plot.getDomainAxis().setTickLabelFont(new Font("Helvetica",Font.PLAIN,13));
        plot.getRangeAxis().setLabelFont(new Font("Helvetica",Font.PLAIN,13));
        plot.getRangeAxis().setTickLabelFont(new Font("Helvetica",Font.PLAIN,13));
        plot.setBackgroundPaint(new Color(196, 225, 255));
        plot.setDomainGridlinesVisible(false);
        plot.setRangeGridlinePaint(Color.BLACK);
        plot.setRangeGridlinesVisible(true);
        BarRenderer renderer = (BarRenderer) plot.getRenderer();
        renderer.setSeriesPaint(0, new Color(0, 128, 255));
        renderer.setSeriesPaint(1, new Color(154, 255, 2));
        
        
        return chart.createBufferedImage(width, height);
    }

    @Override
    public BufferedImage drawImage(int enterpriseID)
    {
        return drawImage(enterpriseID, 600, 380);
    }
    
}
